package com.kakarote.oa.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.kakarote.common.field.utils.FieldUtil;
import com.kakarote.common.log.entity.OperationLog;
import com.kakarote.common.log.enums.ApplyEnum;
import com.kakarote.common.log.enums.OperateObjectEnum;
import com.kakarote.core.common.Const;
import com.kakarote.core.common.enums.FieldEnum;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.examine.entity.ExamineInfoVo;
import com.kakarote.core.feign.examine.service.ExamineService;
import com.kakarote.core.servlet.BaseServiceImpl;
import com.kakarote.core.utils.BaseUtil;
import com.kakarote.oa.common.LanguageFieldUtil;
import com.kakarote.oa.common.OaCodeEnum;
import com.kakarote.oa.entity.BO.ExamineFieldBO;
import com.kakarote.oa.entity.PO.OaExamineData;
import com.kakarote.oa.entity.PO.OaExamineField;
import com.kakarote.oa.entity.PO.OaExamineFieldExtend;
import com.kakarote.oa.mapper.OaExamineFieldMapper;
import com.kakarote.oa.service.IOaExamineDataService;
import com.kakarote.oa.service.IOaExamineFieldExtendService;
import com.kakarote.oa.service.IOaExamineFieldService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 自定义字段表 服务实现类
 * </p>
 *
 * @author zhangzhiwei
 * @since 2020-06-22
 */
@Service
public class OaExamineFieldServiceImpl extends BaseServiceImpl<OaExamineFieldMapper, OaExamineField> implements IOaExamineFieldService {

    @Autowired
    private IOaExamineDataService examineDataService;

    @Autowired
    private ExamineService examineService;

    @Autowired
    private IOaExamineFieldExtendService oaExamineFieldExtendService;

    private static final int TWO = 2;
    private static final int THREE = 3;
    private static final int FOUR = 4;
    private static final int FIVE = 5;
    private static final int SIX = 6;

    @Override
    public List<OaExamineField> queryField(Long id, Boolean needHidden) {

        //当现审批id字段
        List<OaExamineField> list;

        if (ObjectUtil.isEmpty(needHidden) || !needHidden) {
            list = lambdaQuery()
                    .eq(OaExamineField::getExamineCategoryId, id)
                    .eq(OaExamineField::getIsHidden, 0)
                    .orderByAsc(OaExamineField::getSorting).list();
        } else {
            list = lambdaQuery()
                    .eq(OaExamineField::getExamineCategoryId, id)
                    .orderByAsc(OaExamineField::getSorting).list();
        }


        //获取最新审批数据
        ExamineInfoVo examineInfoVo = examineService.queryExamineById(id).getData();
        if (!examineInfoVo.getExamineId().equals(id)) {
            //最新审批字段
            List<OaExamineField> newlist;

            if (ObjectUtil.isEmpty(needHidden) || !needHidden) {
                newlist = lambdaQuery()
                        .eq(OaExamineField::getExamineCategoryId, examineInfoVo.getExamineId())
                        .eq(OaExamineField::getIsHidden, 0)
                        .orderByAsc(OaExamineField::getSorting).list();
            } else {
                newlist = lambdaQuery()
                        .eq(OaExamineField::getExamineCategoryId, examineInfoVo.getExamineId())
                        .orderByAsc(OaExamineField::getSorting).list();
            }

            //如果最新审批字段为空，则使用原审批字段，审批自定义流程的时候会出现这种情况
            if (CollectionUtil.isEmpty(newlist)) {
                newlist = list;
            }

            for (OaExamineField oldField : list) {
                for (OaExamineField newField : newlist) {
                    if (newField.getFieldName().equals(oldField.getFieldName())) {
                        newField.setNewFieldId(newField.getFieldId());
                        newField.setFieldId(oldField.getFieldId());
                    }
                }
            }
            list = newlist;
        }


        list = list.stream().sorted(Comparator.comparing(OaExamineField::getSorting)).collect(Collectors.toList());


        Integer oaType = Optional.ofNullable(examineInfoVo.getOaType()).orElse(0);
        for (OaExamineField oaExamineField : list) {
            //设置字段驼峰式
            oaExamineField.setFieldName(StrUtil.toCamelCase(oaExamineField.getFieldName()));
            if (ObjectUtil.isNotEmpty(oaExamineField.getOptions())) {
                if (BaseUtil.isJSONArray(oaExamineField.getOptions())) {
                    JSONArray jsonArray = JSONUtil.parseArray(oaExamineField.getOptions());
                    oaExamineField.setSetting(new ArrayList<>(jsonArray));
                } else {
                    oaExamineField.setSetting(new ArrayList<>(StrUtil.splitTrim(oaExamineField.getOptions(), Const.SEPARATOR)));
                }
            }
        }
        if (ListUtil.toList(1, 2, 3, 4, 5, 6).contains(oaType)) {
            //设置默认新增字段信息
            setDefaultField(list);
            for (OaExamineField field : list) {
                if (Objects.equals(oaType, 2) && "审批内容".equals(field.getName())) {
                    field.setName("请假事由");
                }
                FieldEnum typeEnum = FieldEnum.parse(field.getType());
                field.setFormType(typeEnum.getFormType());
                if (FieldEnum.SELECT.equals(typeEnum)) {
                    if (Objects.equals(field.getRemark(), FieldEnum.OPTIONS_TYPE.getFormType())) {
                        LinkedHashMap<String, Object> optionsData = JSON.parseObject(field.getOptions(), LinkedHashMap.class);
                        field.setOptionsData(optionsData);
                        field.setSetting(new ArrayList<>(optionsData.keySet()));
                    } else {
                        field.setSetting(new ArrayList<>(StrUtil.splitTrim(field.getOptions(), Const.SEPARATOR)));
                    }
                }

                //添加语言包key
                field.setLanguageKeyMap(LanguageFieldUtil.getFieldNameKeyMap("name_resourceKey", "customField." + "oaExamine" + oaType + ".", field.getFieldName(), field.getSetting()));
            }
        }
        FieldUtil.recordToFormType(list);
        recordToFormType(list);
        return list;
    }

    @Override
    public List<List<OaExamineField>> queryFormPositionField(Long id, Boolean needHidden) {
        List<OaExamineField> list = this.queryField(id, needHidden);
        return FieldUtil.convertFormPositionFieldList(list);
    }

    private void recordToFormType(List<OaExamineField> list) {
        for (OaExamineField record : list) {
            FieldEnum typeEnum = FieldEnum.parse(record.getType());
            record.setFormType(typeEnum.getFormType());
            switch (typeEnum) {
                case CHECKBOX:
                    record.setDefaultValue(StrUtil.splitTrim((CharSequence) record.getDefaultValue(), Const.SEPARATOR));
                case SELECT:
                    if (Objects.equals(record.getRemark(), FieldEnum.OPTIONS_TYPE.getFormType()) && BaseUtil.isJSON(record.getOptions())) {
                        LinkedHashMap<String, Object> optionsData = JSON.parseObject(record.getOptions(), LinkedHashMap.class);
                        record.setOptionsData(optionsData);
                        record.setSetting(new ArrayList<>(optionsData.keySet()));
                    } else {
                        record.setSetting(new ArrayList<>(StrUtil.splitTrim(record.getOptions(), Const.SEPARATOR)));
                    }
                    break;
                case DATE_INTERVAL:
                    String dataValueStr = Optional.ofNullable(record.getDefaultValue()).orElse("").toString();
                    record.setDefaultValue(StrUtil.split(dataValueStr, Const.SEPARATOR));
                    break;
                case USER:
                case STRUCTURE:
                    record.setDefaultValue(new ArrayList<>(0));
                    break;
                case AREA:
                case AREA_POSITION:
                case CURRENT_POSITION:
                    String defaultValue = Optional.ofNullable(record.getDefaultValue()).orElse("").toString();
                    record.setDefaultValue(JSON.parse(defaultValue));
                    break;
                case DETAIL_TABLE:
                    record.setFieldExtendList(oaExamineFieldExtendService.queryOaExamineFieldExtend(record.getNewFieldId() != null ? record.getNewFieldId() : record.getFieldId()));
                    break;
                default:
                    if (ObjectUtil.isEmpty(record.getSetting())) {
                        record.setSetting(new ArrayList<>());
                    }
                    break;
            }
        }
    }

    @Override
    public Boolean updateFieldCategoryId(Long newCategoryId, Long oldCategoryId) {
        if (newCategoryId != null && oldCategoryId != null) {
            List<OaExamineField> oaExamineFields = this.lambdaQuery().eq(OaExamineField::getExamineCategoryId, oldCategoryId).list();
            for (OaExamineField oaExamineField : oaExamineFields) {
                Long fieldId = oaExamineField.getFieldId();
                oaExamineField.setFieldId(null);
                oaExamineField.setExamineCategoryId(newCategoryId);
                save(oaExamineField);
                if (ObjectUtil.equal(oaExamineField.getType(), FieldEnum.DETAIL_TABLE.getType())) {
                    List<OaExamineFieldExtend> oaExamineFieldExtendList = oaExamineFieldExtendService.queryOaExamineFieldExtend(fieldId);
                    for (OaExamineFieldExtend fieldExtend : oaExamineFieldExtendList) {
                        // 20220224 wwl BUG-8335 对复选框进行处理 ↓
                        if (ObjectUtil.isEmpty(fieldExtend.getDefaultValue())) {
                            fieldExtend.setDefaultValue("");
                        } else {
                            boolean isNeedHandle = FieldUtil.equalsByType(fieldExtend.getType(), FieldEnum.AREA, FieldEnum.AREA_POSITION, FieldEnum.CURRENT_POSITION);
                            if (isNeedHandle) {
                                fieldExtend.setDefaultValue(JSON.toJSONString(fieldExtend.getDefaultValue()));
                            }
                            if (fieldExtend.getDefaultValue() instanceof Collection) {
                                fieldExtend.setDefaultValue(StrUtil.join(Const.SEPARATOR, fieldExtend.getDefaultValue()));
                            }
                        }
                        // 20220224 wwl BUG-8335 对复选框进行处理 ↑
                        fieldExtend.setId(null);
                        fieldExtend.setParentFieldId(oaExamineField.getFieldId());
                        oaExamineFieldExtendService.save(fieldExtend);
                    }
                }
            }
            return true;
        }
        return false;
    }

    /**
     * 根据batchId查询values
     *
     * @param batchId batchId
     * @return valuesMap
     */
    @Override
    public Map<Long, String> queryFieldData(String batchId) {
        List<OaExamineData> examineData = examineDataService.lambdaQuery().select(OaExamineData::getFieldId, OaExamineData::getValue).eq(OaExamineData::getBatchId, batchId).list();
        Map<Long, String> dataMap = new HashMap<>(examineData.size(), 1.0f);
        for (OaExamineData data : examineData) {
            dataMap.put(data.getFieldId(), data.getValue());
        }
        return dataMap;
    }

    @Override
    public void transferFieldList(List<OaExamineField> recordList, Integer isDetail) {
        recordList.forEach(record -> {
            Integer dataType = record.getType();
            if (isDetail == TWO) {
                if (FieldEnum.CHECKBOX.getType().equals(dataType)) {
                    if (ObjectUtil.isNotEmpty(record.getValue())) {
                        String[] split = record.getValue().toString().split(",");
                        record.setValue(split);
                    }
                }
            }
            if (ObjectUtil.isNotEmpty(record.getValue())) {
                FieldEnum fieldEnum = FieldEnum.parse(dataType);
                record.setValue(FieldUtil.format2Object(record.getValue(), fieldEnum));
            }
            if (FieldEnum.TAG.getType().equals(record.getType())) {
                if (ObjectUtil.isNotEmpty(record.getValue()) && BaseUtil.isJSON(record.getValue().toString())) {
                    record.setValue(JSONUtil.parseArray(record.getValue().toString()));
                }
            }

        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OperationLog saveField(ExamineFieldBO examineFieldBO) {
        List<OaExamineField> data = examineFieldBO.getData();
        Map<String, List<OaExamineField>> collect = data.stream().collect(Collectors.groupingBy(OaExamineField::getName));
        for (Map.Entry<String, List<OaExamineField>> entry : collect.entrySet()) {
            if (entry.getValue().size() > 1) {
                throw new CrmException(OaCodeEnum.THE_NAME_OF_THE_CUSTOM_FORM_CANNOT_BE_REPEATED);
            }
        }
        Long categoryId = examineFieldBO.getCategoryId();
        ExamineInfoVo category = examineService.queryExamineById(categoryId).getData();
        if (category != null && ListUtil.toList(1, TWO, THREE, FOUR, FIVE, SIX).contains(category.getOaType())) {
            throw new CrmException(OaCodeEnum.SYSTEM_EXAMINE_CAN_NOT_MODIFY);
        }

        OperationLog operationLog = new OperationLog();
        if (category.getLabel() == 0) {
            operationLog.setApply(ApplyEnum.OFFICE_MANAGEMENT);
            operationLog.setApplyObject(OperateObjectEnum.APPROVAL_FLOW);
        } else if (ListUtil.toList(1, 2, 3).contains(category.getLabel())) {
            operationLog.setApply(ApplyEnum.CUSTOMER_MANAGEMENT);
            operationLog.setApplyObject(OperateObjectEnum.BUSINESS_APPROVAL_FLOW);
        }
        operationLog.setOperationObject(category.getExamineName());
        operationLog.setOperationInfo("编辑审批表单信息");

        List<Long> arr = data.stream().map(OaExamineField::getFieldId).filter(Objects::nonNull).collect(Collectors.toList());
        if (!arr.isEmpty()) {
            getBaseMapper().deleteByChooseId(arr, categoryId);
            getBaseMapper().deleteByFieldValue(arr, categoryId);
            oaExamineFieldExtendService.lambdaUpdate().in(OaExamineFieldExtend::getParentFieldId, arr).remove();
        }
        for (int i = 0; i < data.size(); i++) {
            OaExamineField entity = data.get(i);
            if (FieldUtil.equalsByType(entity.getType(), FieldEnum.TAG, FieldEnum.ATTENTION)) {
                if (entity.getSetting() != null && !entity.getSetting().isEmpty()) {
                    entity.setOptions(JSON.toJSONString(entity.getSetting()));
                }
            }
            entity.setUpdateTime(LocalDateTimeUtil.now());
            entity.setExamineCategoryId(categoryId);
            entity.setSorting(i);
            if (ObjectUtil.isEmpty(entity.getDefaultValue())) {
                entity.setDefaultValue("");
            } else {
                boolean isNeedHandle = FieldUtil.equalsByType(entity.getType(), FieldEnum.AREA, FieldEnum.AREA_POSITION, FieldEnum.CURRENT_POSITION);
                if (isNeedHandle) {
                    entity.setDefaultValue(JSON.toJSONString(entity.getDefaultValue()));
                }
                if (entity.getDefaultValue() instanceof Collection) {
                    entity.setDefaultValue(StrUtil.join(Const.SEPARATOR, entity.getDefaultValue()));
                }
            }
            if (entity.getFieldId() != null) {
                if (FieldEnum.DETAIL_TABLE.getType().equals(entity.getType())) {
                    oaExamineFieldExtendService.saveOrUpdateOaExamineFieldExtend(entity.getFieldExtendList(), entity.getFieldId(), true);
                }
                entity.setFieldName(StrUtil.toUnderlineCase(entity.getFieldName()));
                updateById(entity);
                examineDataService.lambdaUpdate().set(OaExamineData::getName, entity.getName()).eq(OaExamineData::getFieldId, entity.getFieldId()).update();
            } else {
                entity.setFieldName(getFieldName(entity.getExamineCategoryId()));
                save(entity);
                if (FieldEnum.DETAIL_TABLE.getType().equals(entity.getType())) {
                    oaExamineFieldExtendService.saveOrUpdateOaExamineFieldExtend(entity.getFieldExtendList(), entity.getFieldId(), false);
                }
            }
        }
        return operationLog;
    }


    @Override
    public void saveDefaultField(Long categoryId) {
        OaExamineField content = new OaExamineField();
        content.setName("审批事由");
        content.setFieldName("content");
        content.setMaxLength(0);
        content.setType(2);
        content.setIsNull(1);
        content.setUpdateTime(LocalDateTimeUtil.now());
        content.setOperating(184);
        content.setFieldType(1);
        content.setSorting(1);
        content.setExamineCategoryId(categoryId);
        this.save(content);
        content.setFieldId(null);
        content.setFieldName("remark");
        content.setIsNull(0);
        content.setName("备注");
        content.setOperating(194);
        content.setFieldType(0);
        content.setSorting(2);
        this.save(content);
        this.saveOADefaultField(categoryId);
    }

    private void saveOADefaultField(Long categoryId) {

        OaExamineField classification = new OaExamineField();
        classification.setName("密级");
        classification.setFieldName("classification");
        classification.setMaxLength(0);
        classification.setType(3);
        classification.setIsNull(1);
        classification.setUpdateTime(LocalDateTimeUtil.now());
        classification.setOperating(255);
        classification.setFieldType(0);
        classification.setExamineCategoryId(categoryId);
        classification.setSorting(3);
        classification.setOptions("普通密级,秘密密级,绝密密级");
        this.save(classification);

        OaExamineField urgency = new OaExamineField();
        urgency.setName("紧急程度");
        urgency.setFieldName("urgency");
        urgency.setMaxLength(0);
        urgency.setType(3);
        urgency.setIsNull(1);
        urgency.setUpdateTime(LocalDateTimeUtil.now());
        urgency.setOperating(255);
        urgency.setFieldType(0);
        urgency.setExamineCategoryId(categoryId);
        urgency.setSorting(4);
        urgency.setOptions("普通,紧急,十分紧急");
        this.save(urgency);


        OaExamineField handled = new OaExamineField();
        handled.setName("经办人");
        handled.setFieldName("handled");
        handled.setMaxLength(0);
        handled.setType(10);
        handled.setIsNull(1);
        handled.setUpdateTime(LocalDateTimeUtil.now());
        handled.setOperating(8);
        handled.setFieldType(1);
        handled.setSorting(5);
        handled.setExamineCategoryId(categoryId);
        this.save(handled);


        OaExamineField telephone = new OaExamineField();
        telephone.setName("联系电话");
        telephone.setFieldName("telephone");
        telephone.setMaxLength(0);
        telephone.setType(7);
        telephone.setIsNull(0);
        telephone.setUpdateTime(LocalDateTimeUtil.now());
        telephone.setOperating(2);
        telephone.setFieldType(1);
        telephone.setSorting(6);
        telephone.setExamineCategoryId(categoryId);
        this.save(telephone);


        OaExamineField submitDeptId = new OaExamineField();
        submitDeptId.setName("提交部门");
        submitDeptId.setFieldName("submitDeptId");
        submitDeptId.setMaxLength(0);
        submitDeptId.setType(12);
        submitDeptId.setIsNull(0);
        submitDeptId.setUpdateTime(LocalDateTimeUtil.now());
        submitDeptId.setOperating(2);
        submitDeptId.setFieldType(1);
        submitDeptId.setSorting(7);
        submitDeptId.setExamineCategoryId(categoryId);
        this.save(submitDeptId);

        OaExamineField submitTime = new OaExamineField();
        submitTime.setName("提交时间");
        submitTime.setFieldName("submitTime");
        submitTime.setMaxLength(0);
        submitTime.setType(13);
        submitTime.setIsNull(1);
        submitTime.setUpdateTime(LocalDateTimeUtil.now());
        submitTime.setOperating(10);
        submitTime.setFieldType(1);
        submitTime.setSorting(8);
        submitTime.setExamineCategoryId(categoryId);
        this.save(submitTime);

    }


    /**
     * 获取fieldName
     *
     * @param categoryId c
     * @return fieldName
     */
    private String getFieldName(Long categoryId) {
        List<OaExamineField> fields = lambdaQuery().select(OaExamineField::getFieldName).eq(OaExamineField::getExamineCategoryId, categoryId).list();
        List<String> names = fields.stream().map(OaExamineField::getFieldName).collect(Collectors.toList());
        String name = "field_" + RandomUtil.randomString(RandomUtil.BASE_CHAR, 6);
        if (names.contains(name)) {
            return getFieldName(categoryId);
        }
        return name;
    }

    public List<OaExamineField> setDefaultField(List<OaExamineField> oaExamineFields) {
        if (CollectionUtil.isEmpty(oaExamineFields)) {
            return oaExamineFields;
        }
        //经办人
        List<OaExamineField> handledList = oaExamineFields.stream().filter(item -> item.getFieldName().equals("handled") || item.getName().equals("经办人")).collect(Collectors.toList());
        //联系电话
        List<OaExamineField> telephoneList = oaExamineFields.stream().filter(item -> item.getFieldName().equals("telephone") || item.getName().equals("联系电话")).collect(Collectors.toList());
        //提交部门
        List<OaExamineField> submitDeptIdList = oaExamineFields.stream().filter(item -> item.getFieldName().equals("submitDeptId") || item.getName().equals("提交部门")).collect(Collectors.toList());
        //提交时间
        List<OaExamineField> submitTimeList = oaExamineFields.stream().filter(item -> item.getFieldName().equals("submitTime") || item.getName().equals("提交时间")).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(handledList)) {
            OaExamineField handled = new OaExamineField();
            handled.setName("经办人");
            handled.setFieldName("handled");
            handled.setMaxLength(0);
            handled.setType(10);
            handled.setIsNull(1);
            handled.setUpdateTime(LocalDateTimeUtil.now());
            handled.setOperating(8);
            handled.setSorting(3);
            handled.setFieldType(1);
            handled.setIsMulti(0);
            handled.setFormPosition("3,0");
            handled.setStylePercent(100);
            oaExamineFields.add(handled);
        }
        if (CollectionUtil.isEmpty(telephoneList)) {
            OaExamineField telephone = new OaExamineField();
            telephone.setName("联系电话");
            telephone.setFieldName("telephone");
            telephone.setMaxLength(0);
            telephone.setType(7);
            telephone.setIsNull(0);
            telephone.setUpdateTime(LocalDateTimeUtil.now());
            telephone.setOperating(2);
            telephone.setFieldType(1);
            telephone.setSorting(5);
            telephone.setFormPosition("4,0");
            telephone.setStylePercent(100);
            oaExamineFields.add(telephone);
        }
        if (CollectionUtil.isEmpty(submitDeptIdList)) {
            OaExamineField submitDeptId = new OaExamineField();
            submitDeptId.setName("提交部门");
            submitDeptId.setFieldName("submitDeptId");
            submitDeptId.setMaxLength(0);
            submitDeptId.setType(12);
            submitDeptId.setIsNull(0);
            submitDeptId.setUpdateTime(LocalDateTimeUtil.now());
            submitDeptId.setOperating(2);
            submitDeptId.setFieldType(1);
            submitDeptId.setSorting(4);
            submitDeptId.setFormPosition("5,0");
            submitDeptId.setStylePercent(100);
            oaExamineFields.add(submitDeptId);
        }
        if (CollectionUtil.isEmpty(submitTimeList)) {
            OaExamineField submitTime = new OaExamineField();
            submitTime.setName("提交时间");
            submitTime.setFieldName("submitTime");
            submitTime.setMaxLength(0);
            submitTime.setType(13);
            submitTime.setIsNull(1);
            submitTime.setUpdateTime(LocalDateTimeUtil.now());
            submitTime.setOperating(10);
            submitTime.setFieldType(1);
            submitTime.setIsHidden(0);
            submitTime.setSorting(6);
            submitTime.setFormPosition("6,0");
            submitTime.setStylePercent(100);
            oaExamineFields.add(submitTime);
        }
        return oaExamineFields;
    }


}
